package Bankmanagement;

import javax.swing.*;
import java.awt.*;
import java.text.DecimalFormat;
import java.util.List;

/**
 * BankSystem Class - Provides a GUI for managing bank accounts and tasks.
 * @author ashongtical
 */
public class BankSystem {
    // Main components
    private BankingAPI taskManager;
    private JPanel mainPanel;

    // Account Creation Panel Components
    public JTextField accountNumberField;
    public JTextField initialBalanceField;
    public JTextField interestRateField;

    // Transaction Panel Components
    public JTextField transactionAccountField;
    public JTextField transactionAmountField;
    public JComboBox<String> transactionTypeCombo;

    // Task List Components
    private DefaultListModel<String> highPriorityModel;
    private DefaultListModel<String> lowPriorityModel;
    private JList<String> highPriorityList;
    private JList<String> lowPriorityList;
    public JTextField taskInputField;

    // Formatting
    private DecimalFormat currencyFormat;

    /**
     * Constructs a new BankSystem with a GUI interface.
     */
    public BankSystem() {
        // Initialize task manager
        taskManager = new BankingTaskManager() {
            @Override
            public boolean accountExists(String number) {
                return false;
            }

            @Override
            public List<String> getAllTasks() {
                return List.of();
            }
        };

        // Initialize currency formatter
        currencyFormat = new DecimalFormat("RMB #,##0.00");

        // Create and setup the main panel
        initializeMainPanel();
    }

    /**
     * Initializes the main JPanel for the application.
     */
    private void initializeMainPanel() {
        mainPanel = new JPanel(new BorderLayout(10, 10));

        // Create main panels
        JPanel accountCreationPanel = createAccountCreationPanel();
        JPanel transactionPanel = createTransactionPanel();
        JPanel taskManagementPanel = createTaskManagementPanel();

        // Add panels to main panel
        mainPanel.add(accountCreationPanel, BorderLayout.NORTH);
        mainPanel.add(transactionPanel, BorderLayout.CENTER);
        mainPanel.add(taskManagementPanel, BorderLayout.SOUTH);
    }

    /**
     * Creates the panel for account creation.
     * @return The account creation panel.
     */
    private JPanel createAccountCreationPanel() {
        JPanel panel = new JPanel(new FlowLayout());
        panel.setBorder(BorderFactory.createTitledBorder("Create Bank Account"));

        // Account Number
        panel.add(new JLabel("Account Number:"));
        accountNumberField = new JTextField(10);
        panel.add(accountNumberField);

        // Initial Balance
        panel.add(new JLabel("Initial Balance:"));
        initialBalanceField = new JTextField(10);
        panel.add(initialBalanceField);

        // Interest Rate
        panel.add(new JLabel("Annual Interest Rate (%):"));
        interestRateField = new JTextField(5);
        panel.add(interestRateField);

        // Create Account Button
        JButton createAccountButton = new JButton("Create Account");
        createAccountButton.addActionListener(e -> createAccount());
        panel.add(createAccountButton);

        return panel;
    }

    /**
     * Handles account creation based on user input.
     */
    public void createAccount() {
        try {
            String accountNumber = accountNumberField.getText().trim();
            if (accountNumber.isEmpty()) {
                throw new IllegalArgumentException("Account number cannot be empty.");
            }
            double initialBalance = Double.parseDouble(initialBalanceField.getText().trim());
            if (initialBalance < 25) {
                throw new IllegalArgumentException("Initial balance must be at least RMB 25.00.");
            }
            double interestRate = Double.parseDouble(interestRateField.getText().trim()) / 100;
            if (interestRate < 0) {
                throw new IllegalArgumentException("Interest rate cannot be negative.");
            }

            // Create account
            taskManager.createAccount(accountNumber, initialBalance, interestRate);

            // Show success message
            JOptionPane.showMessageDialog(mainPanel,
                    "Account Created:\n" +
                            "Number: " + accountNumber + "\n" +
                            "Initial Balance: " + currencyFormat.format(initialBalance) + "\n" +
                            "Interest Rate: " + (interestRate * 100) + "%",
                    "Account Creation Successful",
                    JOptionPane.INFORMATION_MESSAGE);

            System.out.println("Account Created:\n" +
                    "Number: " + accountNumber + "\n" +
                    "Initial Balance: " + currencyFormat.format(initialBalance) + "\n" +
                    "Interest Rate: " + (interestRate * 100) + "%");

            // Clear input fields
            accountNumberField.setText("");
            initialBalanceField.setText("");
            interestRateField.setText("");
        } catch (NumberFormatException ex) {
            JOptionPane.showMessageDialog(mainPanel,
                    "Please enter valid numbers for balance and interest rate.",
                    "Invalid Input",
                    JOptionPane.ERROR_MESSAGE);
        } catch (IllegalArgumentException ex) {
            JOptionPane.showMessageDialog(mainPanel,
                    "Error creating account: " + ex.getMessage(),
                    "Account Creation Error",
                    JOptionPane.ERROR_MESSAGE);
        }
    }

    /**
     * Creates the panel for banking transactions.
     * @return The transaction panel.
     */
    private JPanel createTransactionPanel() {
        JPanel panel = new JPanel(new FlowLayout());
        panel.setBorder(BorderFactory.createTitledBorder("Banking Transactions"));

        // Account Number
        panel.add(new JLabel("Account Number:"));
        transactionAccountField = new JTextField(10);
        panel.add(transactionAccountField);

        // Transaction Amount
        panel.add(new JLabel("Amount:"));
        transactionAmountField = new JTextField(10);
        panel.add(transactionAmountField);

        // Transaction Type
        String[] transactionTypes = {"Deposit", "Withdraw"};
        transactionTypeCombo = new JComboBox<>(transactionTypes);
        panel.add(transactionTypeCombo);

        // Transaction Button
        JButton transactionButton = new JButton("Process Transaction");
        transactionButton.addActionListener(e -> processTransaction());
        panel.add(transactionButton);

        return panel;
    }

    /**
     * Processes a deposit or withdrawal transaction.
     */
    public void processTransaction() {
        try {
            String accountNumber = transactionAccountField.getText().trim();
            if (accountNumber.isEmpty()) {
                throw new IllegalArgumentException("Account number cannot be empty.");
            }
            double amount = Double.parseDouble(transactionAmountField.getText().trim());
            if (amount <= 0) {
                throw new IllegalArgumentException("Transaction amount must be positive.");
            }
            String transactionType = (String) transactionTypeCombo.getSelectedItem();

            // Perform transaction
            if ("Deposit".equals(transactionType)) {
                taskManager.deposit(accountNumber, amount);
            } else {
                taskManager.withdraw(accountNumber, amount);
            }

            // Show success message
            JOptionPane.showMessageDialog(mainPanel,
                    transactionType + " of " + currencyFormat.format(amount) +
                            " to Account " + accountNumber + " successful!",
                    "Transaction Completed",
                    JOptionPane.INFORMATION_MESSAGE);

            // Clear input fields
            transactionAccountField.setText("");
            transactionAmountField.setText("");
        } catch (NumberFormatException ex) {
            JOptionPane.showMessageDialog(mainPanel,
                    "Please enter a valid transaction amount.",
                    "Invalid Input",
                    JOptionPane.ERROR_MESSAGE);
        } catch (IllegalArgumentException | IllegalStateException ex) {
            JOptionPane.showMessageDialog(mainPanel,
                    "Transaction failed: " + ex.getMessage(),
                    "Transaction Error",
                    JOptionPane.ERROR_MESSAGE);
        }
    }

    /**
     * Creates the panel for task management.
     * @return The task management panel.
     */
    private JPanel createTaskManagementPanel() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBorder(BorderFactory.createTitledBorder("Task Management"));

        // Task Input Panel
        JPanel inputPanel = new JPanel(new FlowLayout());
        taskInputField = new JTextField(20);
        JButton addTaskButton = new JButton("Add Task");
        addTaskButton.addActionListener(e -> addTask());
        inputPanel.add(new JLabel("Task:"));
        inputPanel.add(taskInputField);
        inputPanel.add(addTaskButton);

        // Task Lists
        highPriorityModel = new DefaultListModel<>();
        lowPriorityModel = new DefaultListModel<>();
        highPriorityList = new JList<>(highPriorityModel);
        lowPriorityList = new JList<>(lowPriorityModel);

        JPanel listPanel = new JPanel(new GridLayout(1, 2));
        listPanel.add(new JScrollPane(highPriorityList));
        listPanel.add(new JScrollPane(lowPriorityList));

        // Buttons for task management
        JPanel buttonPanel = new JPanel(new FlowLayout());
        JButton removeTaskButton = new JButton("Remove Task");
        JButton changeTaskPriorityButton = new JButton("Change Priority");
        removeTaskButton.addActionListener(e -> removeTask());
        changeTaskPriorityButton.addActionListener(e -> changePriority());
        buttonPanel.add(removeTaskButton);
        buttonPanel.add(changeTaskPriorityButton);

        // Assemble task management panel
        panel.add(inputPanel, BorderLayout.NORTH);
        panel.add(listPanel, BorderLayout.CENTER);
        panel.add(buttonPanel, BorderLayout.SOUTH);

        return panel;
    }

    /**
     * Adds a new task to the task manager.
     */
    public void addTask() {
        String task = taskInputField.getText().trim();
        if (!task.isEmpty()) {
            taskManager.addTask(task);
            updateTaskLists();
            taskInputField.setText("");
        } else {
            JOptionPane.showMessageDialog(mainPanel,
                    "Please enter a valid task description.",
                    "Invalid Input",
                    JOptionPane.ERROR_MESSAGE);
        }
    }

    /**
     * Removes a selected task from the high or low priority list.
     */
    public void removeTask() {
        if (!highPriorityList.isSelectionEmpty()) {
            int index = highPriorityList.getSelectedIndex();
            taskManager.removeTask("high", index);
        } else if (!lowPriorityList.isSelectionEmpty()) {
            int index = lowPriorityList.getSelectedIndex();
            taskManager.removeTask("low", index);
        } else {
            JOptionPane.showMessageDialog(mainPanel,
                    "Please select a task to remove.",
                    "No Task Selected",
                    JOptionPane.WARNING_MESSAGE);
        }
        updateTaskLists();
    }

    /**
     * Changes the priority of a selected task.
     */
    private void changePriority() {
        if (!highPriorityList.isSelectionEmpty()) {
            int index = highPriorityList.getSelectedIndex();
            taskManager.changePriority("high", index);
        } else if (!lowPriorityList.isSelectionEmpty()) {
            int index = lowPriorityList.getSelectedIndex();
            taskManager.changePriority("low", index);
        } else {
            JOptionPane.showMessageDialog(mainPanel,
                    "Please select a task to change priority.",
                    "No Task Selected",
                    JOptionPane.WARNING_MESSAGE);
        }
        updateTaskLists();
    }

    /**
     * Updates the task lists in the GUI.
     */
    private void updateTaskLists() {
        highPriorityModel.clear();
        lowPriorityModel.clear();

        for (String task : taskManager.getHighPriorityTasks()) {
            highPriorityModel.addElement(task);
        }

        for (String task : taskManager.getLowPriorityTasks()) {
            lowPriorityModel.addElement(task);
        }
    }

    /**
     * Returns the main panel for embedding in other applications.
     * @return The main panel.
     */
    public JPanel getMainPanel() {
        return mainPanel;
    }

    /**
     * Returns the task manager for external access.
     * @return The BankingAPI instance.
     */
    public BankingAPI getTaskManager() {
        return taskManager;
    }
}